#include "mainWindow.h"

MainWindow::MainWindow(QWidget* parent):
    QDialog(parent),
    max_alarms(8),
    connected(false),
    noRespondEvent(false),
    powerString("Power: %1 Sound: %2")
{
    setWindowIcon(QIcon(":/icon/WebAlarmClient.ico"));
    initVars();
    createLayout();
    loadSettings();
    createSystemTray();
    makeConnections();
    setMaximumSize(sizeHint());
    setMinimumSize(sizeHint());
    log("Program start");
}

void MainWindow::makeConnections(){
    QObject::connect(connectButton,SIGNAL(clicked()),this,SLOT(startStopConnection()));
    QObject::connect(eventTimer,SIGNAL(timeout()),this,SLOT(updateAlarm()));
    QObject::connect(timeoutTimer,SIGNAL(timeout()),this,SLOT(connectionTimeout()));
    QObject::connect(optionsButton,SIGNAL(clicked()),optionsDialog,SLOT(show()));
    QObject::connect(optionsDialog,SIGNAL(accepted()),this,SLOT(loadSettings()));
    QObject::connect(optionsDialog,SIGNAL(ipChanged(QString,QString)),this,SLOT(changeIp(QString,QString)));
}

void MainWindow::initVars(){
    alarmsEnabled = new bool[max_alarms];
    alarmEvents = new bool[max_alarms];
    alarmNameLabels = new QLabel*[max_alarms];
    alarmStatusLabels = new QLabel*[max_alarms];
    for(int i = 0; i < max_alarms; ++i){
        alarmEvents[i] = false;
    }
    eventTimer = new QTimer();
    timeoutTimer = new QTimer();
    mediaObject = new Phonon::MediaObject(this);
    ado = new Phonon::AudioOutput(Phonon::MusicCategory,this);
    Phonon::createPath(mediaObject,ado);
    playSound = true;
    QDir d;
    if(!d.exists("logs")){
        d.mkdir("logs");
    }
    cThread = 0;
}

void MainWindow::createSystemTray(){
    if(QSystemTrayIcon::isSystemTrayAvailable())
    {
        tray = new QSystemTrayIcon(QIcon(":/icon/WebAlarmClient.ico"),this);
        QMenu* trayContextMenu = new QMenu("Web Alarm Client",this);
        QAction* exitAction = new QAction("Exit",trayContextMenu);
        QObject::connect(exitAction,SIGNAL(triggered()),qApp,SLOT(quit()));
        QObject::connect(tray,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,SLOT(showMainWindow(QSystemTrayIcon::ActivationReason)));
        QAction* optionsAction = new QAction("Options",trayContextMenu);
        QObject::connect(optionsAction,SIGNAL(triggered()),optionsDialog,SLOT(show()));
        trayContextMenu->addAction(optionsAction);
        trayContextMenu->addSeparator();
        trayContextMenu->addAction(exitAction);
        tray->setContextMenu(trayContextMenu);
        tray->show();
    }
}

void MainWindow::createLayout(){
    QString style = "";
    style += "QLabel {font-size: 30px}";
    style += "QProgressBar {border: 2px solid gray; border-radius: 4px; text-align: center}";
    style += "QProgressBar::chunk {background-color: green}";
    style += "QGroupBox {font-size: 20px; color: #707070}";
    style += "QComboBox{border: 2px solid gray; border-radius: 2px; background-color: #FFFFFF; height: 20px}";
    style += "QAbstractItemView {border: 2px solid gray; background-color: #FFFFFF}";
    style += "QComboBox::drop-down {background-color: #C0C0C0}";
    style += "QLineEdit {border: 2px solid gray; border-radius: 2px; background-color: #FFFFFF; height: 20px}";
    style += "QCheckBox::indicator {border: 2px solid gray; background-color: #FFFFFF}";
    style += "QCheckBox::indicator::checked {border: 2px solid gray; background-color: #A0A0A0}";
    style += "QPushButton {border: 2px solid gray; border-radius: 4px; text-align: center; height: 23px; background-color: #D0D0D0; padding-left: 20px; padding-right: 20px}";
    style += "QPushButton::hover {border: 2px solid gray; border-radius: 4px; text-align: center; height: 23px; background-color: #C0C0C0}";
    style += "QPushButton::pressed {border: 2px solid gray; border-radius: 4px; text-align: center; height: 23px; background-color: #FFFFFF}";
    setStyleSheet(style);
    mainLayout = new QHBoxLayout(this);
    alarmLayout = new QGridLayout();
    toolsLayout = new QVBoxLayout();
    infoLayout = new QVBoxLayout();
    batteryLayout = new QHBoxLayout();

    alarmGroupBox = new QGroupBox();
    infoGroupBox = new QGroupBox("Information");
    //infoGroupBox->setStyleSheet();

    for(int i = 0; i < max_alarms; ++i){
        alarmNameLabels[i] = new QLabel(this);
        alarmStatusLabels[i] = new QLabel(this);
        alarmNameLabels[i]->setMinimumWidth(300);
        alarmStatusLabels[i]->setMinimumWidth(100);
        alarmStatusLabels[i]->setAlignment(Qt::AlignCenter);

        alarmLayout->addWidget(alarmNameLabels[i],i+1,1);
        alarmLayout->addWidget(alarmStatusLabels[i],i+1,2);
    }
    optionsDialog = new OptionsDialog(this);
    optionsDialog->setModal(true);
    connectButton = new QPushButton("Connect",this);
    optionsButton = new QPushButton("Options",this);
    connectionStatus = new QLabel("Disconnected",this);
    connectionStatus->setMinimumWidth(200);
    connectionStatus->setAlignment(Qt::AlignCenter);
    powerLabel = new QLabel(powerString.arg(EMPTY_TEXT).arg(EMPTY_TEXT),this);
    powerLabel->setStyleSheet("font-size: 20px");
    batteryLabel = new QLabel("Battery:",this);
    batteryLabel->setStyleSheet("font-size: 20px");
    batteryProgressBar = new QProgressBar(this);
    batteryProgressBar->setRange(0,250);
    batteryProgressBar->setValue(0);
    batteryLayout->addWidget(batteryLabel);
    batteryLayout->addWidget(batteryProgressBar);
    toolsLayout->addWidget(optionsButton);
    toolsLayout->addWidget(connectButton);
    toolsLayout->addStretch();
    infoLayout->addLayout(batteryLayout);
    infoLayout->addWidget(powerLabel);
    infoLayout->addWidget(connectionStatus);
    alarmGroupBox->setLayout(alarmLayout);
    infoGroupBox->setLayout(infoLayout);
    toolsLayout->addWidget(infoGroupBox);
    mainLayout->addWidget(alarmGroupBox);
    mainLayout->addLayout(toolsLayout);
    setLayout(mainLayout);
}

void MainWindow::updateAlarm()
{
    //qDebug("Alarm event");
    bool ev = false;
    for(int i = 0; i < max_alarms; ++i){
        if(alarmEvents[i]){
            if(mediaObject->state() != Phonon::PlayingState && playSound){
                mediaObject->setCurrentSource(audioFiles[i]);
                mediaObject->play();
            }
            ev = true;
            if(alarmNameLabels[i]->styleSheet().contains("red")){
                alarmNameLabels[i]->setStyleSheet("color: black; font-size: 30px");
                alarmStatusLabels[i]->setStyleSheet("color: black; font-size: 30px");
            }
            else {
                alarmNameLabels[i]->setStyleSheet("color: red; font-size: 30px");
                alarmStatusLabels[i]->setStyleSheet("color: red; font-size: 30px");
            }
        }
    }
    if(noRespondEvent){
        ev = true;
        if(mediaObject->state() != Phonon::PlayingState){
            mediaObject->setCurrentSource(errorAudioFile);
            mediaObject->play();
        }

        if(connectionStatus->styleSheet().contains("red")){
            connectionStatus->setStyleSheet("color: black; font-size: 30px");
        }
        else {
            connectionStatus->setStyleSheet("color: red; font-size: 30px");
        }
    }
    if(!ev){
        eventTimer->stop();
        mediaObject->stop();
        for(int i = 0; i < max_alarms; ++i){
            alarmNameLabels[i]->setStyleSheet("color: black; font-size: 30px");
            alarmStatusLabels[i]->setStyleSheet("color: black; font-size: 30px");
        }
        connectionStatus->setStyleSheet("color: black; font-size: 30px");
    }

}


void MainWindow::startStopConnection(){
    if(!connected){
        cThread = new ConnectionThread(hostIPString);
        QObject::connect(cThread,SIGNAL(sig_connected()),this,SLOT(connectedToHost()));
        QObject::connect(cThread,SIGNAL(sig_event_at(int,bool)),this,SLOT(alarmEvent(int,bool)));
        QObject::connect(cThread,SIGNAL(sig_info(int,bool,bool)),this,SLOT(setInfo(int,bool,bool)));
        QObject::connect(cThread,SIGNAL(sig_cant_connect()),this,SLOT(connectionError()));
        cThread->start();
        connectionStatus->setText("Connecting...");
        if(timeoutTimer->isActive()){
            timeoutTimer->stop();
        }
        timeoutTimer->singleShot(CONNECTION_TIMEOUT,this,SLOT(connectionTimeout()));
    }
    else {
        eventTimer->stop();
        connected = false;
        cThread->exit_thread();
        connectionStatus->setText("Disconnecting...");
        cThread->wait();
        QObject::disconnect(cThread,SIGNAL(sig_connected()),this,SLOT(connectedToHost()));
        QObject::disconnect(cThread,SIGNAL(sig_event_at(int,bool)),this,SLOT(alarmEvent(int,bool)));
        QObject::disconnect(cThread,SIGNAL(sig_info(int,bool,bool)),this,SLOT(setInfo(int,bool,bool)));
        QObject::disconnect(cThread,SIGNAL(sig_cant_connect()),this,SLOT(connectionError()));
        powerLabel->setText(powerString.arg(EMPTY_TEXT).arg(EMPTY_TEXT));
        delete cThread;
        cThread = 0;
        disconnectedFromHost();
    }
}

void MainWindow::setInfo(int b, bool p, bool s){
    if(p != power){
        log(QString("Power ") + (p?"ON":"OFF"));
    }
    if(s != playSound){
        log(QString("Sound ") + (s?"ON":"OFF"));
    }
    playSound = s;
    power = p;
    if(b < 0){
        b = 0;
    }
    if(b > 250) {
        b = 250;
    }
    if(b < 90) {
        batteryProgressBar->setStyleSheet("QProgressBar::chunk {background-color: red}");
    }
    else if(b < 180) {
        batteryProgressBar->setStyleSheet("QProgressBar::chunk {background-color: yellow}");
    }
    else {
        batteryProgressBar->setStyleSheet("QProgressBar::chunk {background-color: green}");
    }
    batteryProgressBar->setValue(b);
    powerLabel->setText(powerString.arg(p?ON_TEXT:OFF_TEXT).arg(s?ON_TEXT:OFF_TEXT));
}

void MainWindow::connectedToHost(){
    connected = false;
    log("Connected");
    connected = true;
    noRespondEvent = false;
    optionsButton->setEnabled(false);
    connectionStatus->setText("Connected");
    connectButton->setText("Disconnect");
}

void MainWindow::disconnectedFromHost(){
    log("Disconnected");
    connected = false;
    optionsButton->setEnabled(true);
    connectionStatus->setText("Disconnected");
    connectButton->setText("Connect");
    batteryProgressBar->setValue(0);
    powerLabel->setText(powerString.arg(EMPTY_TEXT).arg(EMPTY_TEXT));
}

void MainWindow::showMainWindow(QSystemTrayIcon::ActivationReason r){
    if(r == QSystemTrayIcon::Trigger){
        this->show();
    }
}


void MainWindow::closeEvent(QCloseEvent *e){
    if(0 != tray){
        tray->showMessage("Web Alarm Client","Web Alarm Client is now in your system tray");
        e->ignore();
        //tray->hide();
        this->hide();
    }
    else{
        //tray->hide();
        e->accept();
    }
}

void MainWindow::loadSettings()
{
    QSettings settings("ShH Soft","WebAlarmClient");
    audioFiles.clear();
    settings.beginGroup("Alarms");
    for(int i = 0; i < max_alarms; ++i){
        alarmsEnabled[i] = settings.value(QString("enableCheckBox%1").arg(i)).toBool();
        alarmNameLabels[i]->setVisible(alarmsEnabled[i]);
        alarmStatusLabels[i]->setVisible(alarmsEnabled[i]);
        alarmNameLabels[i]->setText(settings.value(QString("nameLineEdit%1").arg(i)).toString());
        alarmStatusLabels[i]->setText("OK");
        audioFiles.push_back("audio/" + settings.value(QString("audio%1").arg(i)).toString());
    }
    settings.endGroup();
    errorAudioFile = QString("audio/") + settings.value("errorAudio").toString();
    hostIPString = settings.value("hostIP").toString();
    qApp->processEvents();
    setFixedSize(sizeHint());
}

void MainWindow::alarmEvent(int i,bool e){
    if(e){
        log(QString("Alarm in " + alarmNameLabels[i]->text()));
    }
    else {
        log(QString("Alarm stoped " + alarmNameLabels[i]->text()));
    }
    alarmEvents[i] = e;
    if(!eventTimer->isActive()){
        eventTimer->start(EVENT_BLINK_TIME);
    }
}

void MainWindow::connectionError(){
    log("Connection error");
    connectionStatus->setText("Error");
    noRespondEvent = true;
    batteryProgressBar->setValue(0);
    powerLabel->setText(powerString.arg(EMPTY_TEXT).arg(EMPTY_TEXT));
    if(!eventTimer->isActive()){
        eventTimer->start(EVENT_BLINK_TIME);
    }
}


void MainWindow::log(QString ev) {
    const QString fileName = QString("logs/" + QDate::currentDate().toString("ddMMyy") + ".log");
    QFile file(fileName);
    if(file.exists()){
        if(!file.open(QIODevice::Append | QIODevice::Text)){
            connectionStatus->setText("Log error");
            return;
        }
    }
    else {
        if(!file.open(QIODevice::WriteOnly | QIODevice::Text)){
            connectionStatus->setText("Log error");
            return;
        }
    }
    //qDebug(QString("Loged: " + ev).toAscii());
    QTextStream out(&file);

    out<<ev<<" at "<<QTime::currentTime().toString("HH:mm:ss");
    endl(out);
    if(connected) {
        out<<powerString.arg(power?"ON":"OFF").arg(playSound?"ON":"OFF");
        endl(out);
        for(int i = 0; i < max_alarms; ++i){
            if(alarmsEnabled[i]){
                out<<alarmNameLabels[i]->text()<<"................"<<alarmStatusLabels[i]->text();
                endl(out);
            }
        }
    }
    endl(endl(endl(out)));
}


void MainWindow::changeIp(QString i, QString m){
    log("IP changed to" + i + " mask " + m);
    ipcThread = new IpChangeThread(hostIPString,i,m);
    QObject::connect(ipcThread,SIGNAL(sig_msg(QString)),this,SLOT(ipChangeMessage(QString)));
    ipcThread->start();
}

void MainWindow::ipChangeMessage(QString msg){
    connectionStatus->setText("Change " + msg);
    QObject::disconnect(ipcThread,SIGNAL(sig_msg(QString)),this,SLOT(ipChangeMessage(QString)));
    delete ipcThread;
    ipcThread = 0;
}

void MainWindow::connectionTimeout(){
    //qDebug("Timeouting :)");
    if(connected){
        //qDebug("Abort timeouting :/");
        return;
    }
    cThread->exit_thread();
    cThread->wait();
    connected = false;
    QObject::disconnect(cThread,SIGNAL(sig_connected()),this,SLOT(connectedToHost()));
    QObject::disconnect(cThread,SIGNAL(sig_event_at(int,bool)),this,SLOT(alarmEvent(int,bool)));
    QObject::disconnect(cThread,SIGNAL(sig_info(int,bool,bool)),this,SLOT(setInfo(int,bool,bool)));
    QObject::disconnect(cThread,SIGNAL(sig_cant_connect()),this,SLOT(connectionError()));
    delete cThread;
    cThread = 0;
    log("Connection timeout");
    connectionStatus->setText("Can't connect");
}

MainWindow::~MainWindow(){
    if(cThread != 0){
        cThread->exit_thread();
    }
    if(timeoutTimer->isActive()){
        timeoutTimer->stop();
    }
    log("Program exit");
}
